一覧に戻る

AWS CDK v2(TypeScript)でパブリックアクセス可能なEC2を定義する

#AWS#EC2#TypeScript#CDK

バージョン

  • aws-cdk-lib: 2.56.0
  • cdk-ec2-key-pair: 3.3.1

TL;DR

ec2.InstanceクラスではパブリックIPの自動割り当てが出来ない(オプションにNetworkInterfaceを定義出来ない。実装されていない。Issueはあるみたいだけどプライオリティ低い)。

import * as ec2 from 'aws-cdk-lib/aws-ec2';
const ec2Instance = new ec2.Instance(this, 'Instance', {
    vpc,
    instanceType: ec2.InstanceType.of(
        ec2.InstanceClass.T2,
        ec2.InstanceSize.MICRO,
    ),
    machineImage: ami,
    securityGroup: securityGroup,
    keyName: key.keyPairName,
    role: role,
});

パブリックIPの自動割り当てにはec2.CfnInstanceクラスを利用する必要がある。実際、ec2.Instanceと比べて記述量がさほど変わらないのでそんなに辛くない、はず。

import * as ec2 from 'aws-cdk-lib/aws-ec2';
const cfnInstance = new ec2.CfnInstance(this, 'CfnInstance', {
    imageId: new ec2.AmazonLinuxImage().getImage(this).imageId,
    instanceType: new ec2.InstanceType('t2.micro').toString(),
    keyName: key.keyPairName,
    networkInterfaces: [
        {
            deviceIndex: '0',
            associatePublicIpAddress: true,
            deleteOnTermination: true,
            subnetId: vpc.publicSubnets[0].subnetId,
            groupSet: [securityGroup.securityGroupId],
        },
    ],
});

CDKのStack全コード

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';

import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as keypair from 'cdk-ec2-key-pair';

export class SampleStack extends cdk.Stack {
    constructor(scope: Construct, id: string, props?: cdk.StackProps) {
        super(scope, id, props);

        // Look up the default VPC
        const vpc = ec2.Vpc.fromLookup(this, 'VPC', {
            vpcId: 'sample-vpc-id',
        });

        // Create a key pair to be used with this EC2 Instance
        const key = new keypair.KeyPair(this, 'KeyPair', {
            name: 'sample-keypair',
            description: 'Key Pair created with CDK Deployment',
        });
        key.grantReadOnPublicKey;

        // Security group for the EC2 instance
        const securityGroup = new ec2.SecurityGroup(this, 'SecurityGroup', {
            vpc,
            description: 'Allow SSH (TCP port 22) in',
            allowAllOutbound: true,
        });

        // Allow SSH access on port tcp/22
        securityGroup.addIngressRule(
            ec2.Peer.anyIpv4(),
            ec2.Port.tcp(22),
            'Allow SSH Access',
        );

        const cfnInstance = new ec2.CfnInstance(this, 'CfnInstance', {
            imageId: new ec2.AmazonLinuxImage().getImage(this).imageId,
            instanceType: new ec2.InstanceType('t2.micro').toString(),
            keyName: key.keyPairName,
            networkInterfaces: [
                {
                    deviceIndex: '0',
                    associatePublicIpAddress: true, // パブリックIPの自動割り当て
                    deleteOnTermination: true,
                    subnetId: vpc.publicSubnets[0].subnetId,
                    groupSet: [securityGroup.securityGroupId],
                },
            ],
        });
    }
}
  • 上記は、パブリックサブネットを持つ既存のVPC以下にEC2インスタンスを追加する例(既存VPCはsample-vpc-idというVPC-IDを用いて参照している)。
  • キーペアはSecretsManagerに保存される(マネジメントコンソール上で、秘密鍵が手に入る)。
  • 上記の例では任意のIPアドレスからのSSHを許可していてセキュリティ的にはよくない。